package cn.enilu.guns.admin.modular.system.controller;

import cn.enilu.guns.admin.core.base.controller.BaseController;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import static cn.enilu.guns.admin.core.support.HttpKit.getResponse;

/**
 * 字典控制器
 *
 * @author enilu
 * @Date 2018年4月19日 22:55:31
 */
@Controller
@RequestMapping("/file")
public class FileController extends BaseController {
    private Logger logger = LoggerFactory.getLogger(FileController.class);
    @Value("${guns.download}")
    private String downloadReportPath;

    private final Map<String, String> contentTypeMap = new HashMap(){
        {
            put(".doc", "application/msword");
            put(".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
            put(".rtf", "application/rtf");
            put(".xls", "application/x-excel");
            put(".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            put(".ppt", "application/vnd.ms-powerpoint");
            put(".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
            put(".pps", "application/vnd.ms-powerpoint");
            put(".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow");
            put(".pdf", "application/pdf");
            put(".swf", "application/x-shockwave-flash");
            put(".dll", "application/x-msdownload");
            put(".exe", "application/octet-stream");
            put(".msi", "application/octet-stream");
            put(".chm", "application/octet-stream");
            put(".cab", "application/octet-stream");
            put(".ocx", "application/octet-stream");
            put(".rar", "application/octet-stream");
            put(".tar", "application/x-tar");
            put(".tgz", "application/x-compressed");
            put(".zip", "application/x-zip-compressed");
            put(".z", "application/x-compress");
            put(".wav", "audio/wav");
            put(".wma", "audio/x-ms-wma");
            put(".wmv", "video/x-ms-wmv");
            put(".mp3", "audio/mpeg");
            put(".mp2", "audio/mpeg");
            put(".mpe", "audio/mpeg");
            put(".mpeg", "audio/mpeg");
            put(".mpg", "audio/mpeg");
            put(".rm", "application/vnd.rn-realmedia");
            put(".mid", "audio/mid");
            put(".midi", "audio/mid");
            put(".rmi", "audio/mid");
            put(".bmp", "image/bmp");
            put(".gif", "image/gif");
            put(".png", "image/png");
            put(".tif", "image/tiff");
            put(".tiff", "image/tiff");
            put(".jpe", "image/jpeg");
            put(".jpeg", "image/jpeg");
            put(".jpg", "image/jpeg");
            put(".txt", "text/plain");
            put(".xml", "text/xml");
            put(".html", "text/html");
            put(".css", "text/css");
            put(".js", "text/javascript");
            put(".mht", "message/rfc822");
            put(".mhtml", "message/rfc822");
        }
    };

    @RequestMapping("download")
    @ResponseBody
    public String downloadFile(String filePath, String fileName){

        try
        {

            filePath = Paths.get(downloadReportPath, filePath).toString();
            File file = new File(filePath);
            if(file.exists()){
                if(Strings.isNullOrEmpty(fileName)){
                    fileName = file.getName();
                }
                String fileSuffix = filePath.substring(filePath.lastIndexOf("."));
                setResponseStream(file, fileName, fileSuffix);
                return null;
            }
        }
        catch (Exception ex)
        {
            logger.error("下载文件[{}]，异常：", filePath, ex);
            ex.printStackTrace();
            return "获取文件异常:" + ex.getMessage();
        }
        return "文件不存在";
    }

    /**
     * Response返回文件流内容
     * @param file 文件
     * @param showName 保存名
     * @throws IOException
     */
    private void setResponseStream(File file, String showName, String fileSuffix) throws IOException {

        String contentType = "application/octet-stream";
        if(contentTypeMap.containsKey(fileSuffix)){
            contentType = contentTypeMap.get(fileSuffix);
        }

        String showFileName = toUtf8String(showName);
        getHttpServletResponse().setContentType(contentType);
        getHttpServletResponse().addHeader("Content-Disposition", (new StringBuilder("attachment;filename=")).append(showFileName).toString());
        FileInputStream fileInputStream   =null;
        OutputStream ops =null;
        try {

            fileInputStream = new FileInputStream(file);
            ops = getHttpServletResponse().getOutputStream();
            int length = FileCopyUtils.copy(fileInputStream, ops);
            getHttpServletResponse().setContentLength(length);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }
    }


    private String toUtf8String(String fileName){
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < fileName.length(); i++) {
            char c = fileName.charAt(i);
            if (c >= 0 && c <= 255) {
                sb.append(c);
            } else {
                byte[] b;
                try {
                    b = Character.toString(c).getBytes("utf-8");
                } catch (Exception ex) {
                    logger.error("将文件名中的汉字转为UTF8编码的串时错误，输入的字符串为[{}],异常信息：", fileName, ex);
                    b = new byte[0];
                }
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];
                    if (k < 0) {
                        k += 256;
                    }
                    sb.append("%" + Integer.toHexString(k).toUpperCase());
                }
            }
        }
        return sb.toString();
    }
}
